import type { Ref } from 'react'
import { useEffect, useRef } from 'react'
import { useStore } from '../../store'
import { useSandboxEle } from '../../store/sandboxEleStore'
import { SandboxProxy } from './SandboxProxy'
import defaultImportMap from './defaultImportMap.json?raw'
import sandboxDoc from './sandboxDoc.html?raw'

const defaultPlaceHolder = '<div id="app"></div>'

function useSandbox(
  containerRef: Ref<HTMLDivElement>,
  handlers: Record<string, any>,
  updateViewer: () => void,
) {
  const proxyRef = useRef<SandboxProxy>()
  const store = useStore()
  const [_, setSandbox] = useSandboxEle()
  const sandboxRef = useRef(createSandbox(
    store.importMap || defaultImportMap,
    store.placeHolder || defaultPlaceHolder,
  ))
  useEffect(() => {
    const sandbox = sandboxRef.current
    if (proxyRef.current)
      return
    sandbox.addEventListener('load', updateViewer)

    // @ts-expect-error ref error
    containerRef.current?.appendChild(sandbox)
    proxyRef.current = new SandboxProxy(sandbox, handlers)
    setSandbox(sandbox)

    return () => {
      sandbox.removeEventListener('load', updateViewer)
    }
  }, [])

  return proxyRef
}

function createSandbox(importMap: string, placeHolder: string) {
  const sandbox = document.createElement('iframe')
  sandbox.className = 'w-full h-full'
  sandbox.setAttribute(
    'sandbox',
    [
      'allow-forms',
      'allow-modals',
      'allow-pointer-lock',
      'allow-popups',
      'allow-same-origin',
      'allow-scripts',
      'allow-top-navigation-by-user-activation',
    ].join(' '),
  )
  const sandboxSrc = sandboxDoc
    .replace(/<!--IMPORT_MAP-->/, importMap)
    .replace(/<!--PREVIEW-OPTIONS-PLACEHOLDER-HTML-->/, placeHolder)

  sandbox.src = '/'
  sandbox.srcdoc = sandboxSrc

  return sandbox
}

export { useSandbox }
